using System;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;


namespace Tic_Tac_Toe
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        StringBuilder stringBuilder;
        SpriteBatch spriteBatch;

        SpriteFont text;
        #region Textures
        Texture2D mainScreen;
        Texture2D hostScreen;
        Texture2D joinScreen;
        Texture2D background;
        Texture2D grid;
        Texture2D ohs;
        Texture2D exes;
        #endregion
        Keys[] prevKeys;

        bool isExesTurn = true;
        bool isSelected = false;

        bool endGame  = false;
        bool drawGame = false;
        bool exesWon  = false;
        bool ohsWon   = false;

        bool isMainScreen = true;
        bool isGameScreen = false;
        bool isHostScreen = false;
        bool isJoinScreen = false;

        int[,] iGrid = new int[,]
                {
                    {0, 0, 0},
                    {0, 0, 0},
                    {0, 0, 0}
                };
        int catCount  = 0;
        int menuItems = 0;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            this.IsMouseVisible = true;
        }

        protected override void Initialize()
        {
            stringBuilder = new StringBuilder();
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            mainScreen = Content.Load<Texture2D>("Screens/MainScreen");
            hostScreen = Content.Load<Texture2D>("Screens/HostScreen");
            joinScreen = Content.Load<Texture2D>("Screens/JoinScreen");
            background = Content.Load<Texture2D>("background");
            grid = Content.Load<Texture2D>("grid");
            ohs = Content.Load<Texture2D>("o's");
            exes = Content.Load<Texture2D>("x's");
            text = Content.Load<SpriteFont>("text");

        }
        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.End))
                this.Exit();

            UpdateGame(gameTime);

            base.Update(gameTime);
        }
        void UpdateGame(GameTime gameTime)
        {
            if (isMainScreen)
                UpdateMainScreen(gameTime);
            else if (isHostScreen)
            {
                TcpListener tcpHost = new TcpListener(IPAddress.Parse("198.162.5.161"), 60000);
                UpdateHostScreen(tcpHost);
            }
            else if (isJoinScreen)
            {
                TcpClient tcpClient = new TcpClient();
                UpdateJoinScreen(tcpClient);
            }
            else if (isGameScreen)
                UpdateGameScreen(gameTime);
        }
        void UpdateMainScreen(GameTime gameTime)
        {
            
            if (Mouse.GetState().X > 681 && Mouse.GetState().Y > 278 && Mouse.GetState().X < 718 && Mouse.GetState().Y < 291)
                menuItems = 0;
            else if (Mouse.GetState().X > 681 && Mouse.GetState().Y > 345 && Mouse.GetState().X < 718 && Mouse.GetState().Y < 362)
                menuItems = 1;
            else if (Mouse.GetState().X > 681 && Mouse.GetState().Y > 406 && Mouse.GetState().X < 718 && Mouse.GetState().Y < 419)
                menuItems = 2;

            if (Mouse.GetState().LeftButton.Equals(ButtonState.Pressed)
                &&Mouse.GetState().X > 681 && Mouse.GetState().Y > 278
                && Mouse.GetState().X < 718 && Mouse.GetState().Y < 419)
            {
                if (menuItems == 0)
                    isHostScreen = true;
                else if (menuItems == 1)
                    isJoinScreen = true;
                else if (menuItems == 2)
                    this.Exit();

                isMainScreen = false;
            }
            
            if (Keyboard.GetState().IsKeyDown(Keys.O))
            {
                isGameScreen = true;
                isHostScreen = false;
            }
        }
        void UpdateHostScreen(TcpListener tcpHost)
        {
            #region Host Screen Input
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            {
                isMainScreen = true;
                isHostScreen = false;
            }
            #endregion
            tcpHost.Start();
            TcpClient client = tcpHost.AcceptTcpClient();
        }
        void UpdateJoinScreen(TcpClient tcpClient)
        {
            #region Join Screen Input
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            {
                isMainScreen = true;
                isJoinScreen = false;
            }

            //I.P. Request
            Keys[] keys = Keyboard.GetState().GetPressedKeys();
            foreach (Keys key in keys)
            {
                if (prevKeys.Contains<Keys>(key))
                    continue;

                int numKey = (int)key;

                if (key == Keys.Back || key == Keys.Delete)
                {
                    if (stringBuilder.Length == 0)
                        continue;
                    else
                        stringBuilder.Remove(stringBuilder.Length - 1, 1);
                }
                else if (numKey >= 48 && numKey <= 57)
                    stringBuilder.Append(numKey - 48);
                else if (numKey >= 96 && numKey <= 105)
                    stringBuilder.Append(numKey - 96);
                else if (numKey == 110 || numKey == 190)
                    stringBuilder.Append(".");
            }
            prevKeys = keys;
            #endregion
        }
        void UpdateGameScreen(GameTime gameTime)
        {
            if (Mouse.GetState().LeftButton.Equals(ButtonState.Pressed) && !endGame)
            {
                #region X Position
                int x = Mouse.GetState().X;
                if (100 < x && x <= 300)
                    x = 0;
                else if (300 < x && x <= 500)
                    x = 1;
                else if (500 < x && x <= 700)
                    x = 2;
                #endregion

                #region Y Position
                int y = Mouse.GetState().Y;
                if (0 < y && y <= 200)
                    y = 0;
                else if (200 < y && y <= 400)
                    y = 1;
                else if (400 < y && y <= 600)
                    y = 2;
                #endregion

                #region Ex or Oh Assignment
                if (x > -1 && x < 3 && y > -1 && y < 3)
                {
                    if (iGrid[y, x] == 0)
                    {
                        if (isExesTurn)
                        {
                            iGrid[y, x] = 1;
                            isExesTurn = false;
                        }
                        else
                        {
                            iGrid[y, x] = 2;
                            isExesTurn = true;
                        }
                    }
                }
                #endregion
            }

            #region Win Conditions
            if (iGrid[0, 0] == 1 && iGrid[0, 1] == 1 && iGrid[0, 2] == 1
              ||iGrid[1, 0] == 1 && iGrid[1, 1] == 1 && iGrid[1, 2] == 1
              ||iGrid[2, 0] == 1 && iGrid[2, 1] == 1 && iGrid[2, 2] == 1
              ||iGrid[0, 0] == 1 && iGrid[1, 0] == 1 && iGrid[2, 0] == 1
              ||iGrid[0, 1] == 1 && iGrid[1, 1] == 1 && iGrid[2, 1] == 1
              ||iGrid[0, 2] == 1 && iGrid[1, 2] == 1 && iGrid[2, 2] == 1
              ||iGrid[0, 0] == 1 && iGrid[1, 1] == 1 && iGrid[2, 2] == 1
              ||iGrid[2, 0] == 1 && iGrid[1, 1] == 1 && iGrid[0, 2] == 1)
            {
                endGame  = true;
                exesWon  = true;
                ohsWon   = false;
                drawGame = false;
            }
            else if (iGrid[0, 0] == 2 && iGrid[0, 1] == 2 && iGrid[0, 2] == 2
              || iGrid[1, 0] == 2 && iGrid[1, 1] == 2 && iGrid[1, 2] == 2
              || iGrid[2, 0] == 2 && iGrid[2, 1] == 2 && iGrid[2, 2] == 2
              || iGrid[0, 0] == 2 && iGrid[1, 0] == 2 && iGrid[2, 0] == 2
              || iGrid[0, 1] == 2 && iGrid[1, 1] == 2 && iGrid[2, 1] == 2
              || iGrid[0, 2] == 2 && iGrid[1, 2] == 2 && iGrid[2, 2] == 2
              || iGrid[0, 0] == 2 && iGrid[1, 1] == 2 && iGrid[2, 2] == 2
              || iGrid[2, 0] == 2 && iGrid[1, 1] == 2 && iGrid[0, 2] == 2)
            {
                endGame = true;
                ohsWon = true;
                exesWon = false;
                drawGame = false;
            }
            else
            {
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        if (iGrid[i, j] != 0)
                            catCount++;
                    }

                    if (catCount == 8)
                    {
                        endGame = true;
                        drawGame = true;
                    }
                    catCount = 0;
                }
            }
            
            #endregion

            if (Keyboard.GetState().IsKeyDown(Keys.Enter) && endGame)
            {
                #region Game Reset
                iGrid = new int[,]
                {
                    {0, 0, 0},
                    {0, 0, 0},
                    {0, 0, 0}
                };

                catCount = 0;

                exesWon  = false;
                ohsWon   = false;
                endGame  = false;
                drawGame = false;
                #endregion
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            {
                isMainScreen = true;
                isGameScreen = false;
            }
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Green);
            spriteBatch.Begin();

            if (isMainScreen)
                DrawMainScreen(spriteBatch);
            else if (isHostScreen)
                DrawHostScreen(spriteBatch);
            else if (isJoinScreen)
                DrawJoinScreen(spriteBatch);
            else if (isGameScreen)
                DrawGameScreen(spriteBatch);

            spriteBatch.End();
            base.Draw(gameTime);
        }
        void DrawMainScreen(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(mainScreen, Vector2.Zero, Color.White);
            spriteBatch.DrawString(text, "Host", new Vector2(679, 273), menuItems == 0 ? Color.White : Color.Black);
            spriteBatch.DrawString(text, "Join", new Vector2(679, 340), menuItems == 1 ? Color.White : Color.Black);
            spriteBatch.DrawString(text, "Exit", new Vector2(679, 400), menuItems == 2 ? Color.White : Color.Black);
        }
        void DrawHostScreen(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(hostScreen, Vector2.Zero, Color.White);
        }
        void DrawJoinScreen(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(joinScreen, Vector2.Zero, Color.White);
            spriteBatch.DrawString(text, stringBuilder.ToString(), new Vector2(324, 500), Color.Black);
        }
        void DrawGameScreen(SpriteBatch spriteBatch)
        { 
            spriteBatch.Draw(background, Vector2.Zero, Color.White);
            spriteBatch.Draw(grid, Vector2.Zero, Color.White);

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (iGrid[i, j] == 1)
                        spriteBatch.Draw(exes, new Vector2(j * 200 + 100, i * 200), Color.White);
                    if (iGrid[i, j] == 2)
                        spriteBatch.Draw(ohs, new Vector2(j * 200 + 100, i * 200), Color.White);
                }
            }

            if (endGame)
            {
                if (exesWon)
                    spriteBatch.DrawString(text, "X's Won;\nPress 'Enter' to Play Again", Vector2.Zero, Color.CornflowerBlue);
                if (ohsWon)
                    spriteBatch.DrawString(text, "O's Won;\nPress 'Enter' to Play Again", Vector2.Zero, Color.CornflowerBlue);
                if (drawGame)
                    spriteBatch.DrawString(text, "Draw Game;\nPress 'Enter' to Play Again", Vector2.Zero, Color.CornflowerBlue);
            }
        }
    }
}
